﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.ComponentModel.Design;
using System.Drawing.Design;
using System.Xml.Linq;
using System.Xml;
using CommonLibrary.Common;
using CommonLibrary.CustControls;
using System.Text.RegularExpressions;
using System.IO;

namespace WfDesignBD
{
    public partial class FrmDesign : Form
    {
        private List<DesignSurface> surface;
        private ISelectionService selectionService;
        private List<MenuCommandService> menuCommandService;
        private DemoToolboxService toolBoxService;
        private static OpenFileDialog fileDialog;

        private const Int32 defaultTabCount = 2;

        private String tempPath;

        #region 构造器

        public FrmDesign()
        {
            InitializeComponent();
            surface = new List<DesignSurface>();
            menuCommandService = new List<MenuCommandService>();

            tempPath = CommonMethod.BaseUrl;
            tempPath = Path.Combine(tempPath, "Temp");
            Directory.CreateDirectory(tempPath);

            this.tabControl1.SelectedIndexChanged += delegate(Object sender, EventArgs e)
            {
                var index = this.tabControl1.SelectedIndex == -1 ? 0 : tabControl1.SelectedIndex;
                getSelectAttr(index);
            };

            this.FormClosing += delegate(Object sender, FormClosingEventArgs e)
            {
                Directory.Delete(tempPath, true);
            };
        }
        private void Form1_Load(object sender, EventArgs e)
        {
            toolBoxService = new DemoToolboxService();
            toolBoxService.ToolBox = new ListBox();
            toolBoxService.ToolBox.Items.Add("Point");
            toolBoxService.ToolBox.Items.Add(new ToolboxItem(typeof(BD_Label)));
            toolBoxService.ToolBox.Items.Add(new ToolboxItem(typeof(BD_Button)));
            toolBoxService.ToolBox.Items.Add(new ToolboxItem(typeof(BD_TextBox)));
            toolBoxService.ToolBox.Items.Add(new ToolboxItem(typeof(BD_CheckBox)));
            //toolBoxService.ToolBox.Items.Add(new ToolboxItem(typeof(CheckedListBox)));
            toolBoxService.ToolBox.Items.Add(new ToolboxItem(typeof(BD_ComboBox)));
            toolBoxService.ToolBox.Items.Add(new ToolboxItem(typeof(BD_RadioButton)));
            //toolBoxService.ToolBox.Items.Add(new ToolboxItem(typeof(GroupBox)));
            //toolBoxService.ToolBox.Items.Add(new ToolboxItem(typeof(ListBox)));
            //toolBoxService.ToolBox.Items.Add(new ToolboxItem(typeof(ListView)));
            //toolBoxService.ToolBox.Items.Add(new ToolboxItem(typeof(MonthCalendar)));
            //toolBoxService.ToolBox.Items.Add(new ToolboxItem(typeof(NumericUpDown)));
            //toolBoxService.ToolBox.Items.Add(new ToolboxItem(typeof(Panel)));
            toolBoxService.ToolBox.Items.Add(new ToolboxItem(typeof(BD_RichTextBox)));
            toolBoxService.ToolBox.Items.Add(new ToolboxItem(typeof(BD_PictureBox)));
            toolBoxService.ToolBox.Items.Add(new ToolboxItem(typeof(BD_DateTimePicker)));
            toolBoxService.ToolBox.Items.Add(new ToolboxItem(typeof(BD_DataGridView)));
            toolBoxService.ToolBox.Items.Add(new ToolboxItem(typeof(BD_Horizon)));
            toolBoxService.ToolBox.Items.Add(new ToolboxItem(typeof(BD_Vertical)));
            toolBoxService.ToolBox.Items.Add(new ToolboxItem(typeof(BD_TreeView_Employee)));
            toolBoxService.ToolBox.Dock = DockStyle.Fill;
            this.panel1.Controls.Add(toolBoxService.ToolBox);

            var tabCount = this.tabControl1.TabCount;

            for (int index = 0; index < tabCount; index++)
                produSurface(index);

            //IDesignerHost host = (IDesignerHost)surface[0].GetService(typeof(IDesignerHost));
            //Control root = (Control)host.RootComponent;
            //var button = (Control)host.CreateComponent(typeof(BD_Button));
            //root.Controls.Add(button);

            // 默认绑定第一个tabpage的选择属性
            getSelectAttr(0);

            change();
        }

        #endregion

        #region 事件

        /// <summary>
        ///  生成surface
        /// </summary>
        /// <param name="index"></param>
        private void produSurface(Int32 index)
        {
            surface.Add(new DesignSurface());
            IServiceContainer container = surface[index].GetService(typeof(IServiceContainer)) as IServiceContainer;

            menuCommandService.Add(new MenuCommandService(surface[index]));
            if (container != null)
            {
                container.AddService(typeof(IToolboxService), toolBoxService);
                container.AddService(typeof(IMenuCommandService), menuCommandService[index]);
            }

            surface[index].BeginLoad(typeof(Form));
            Control view = (Control)surface[index].View;
            view.Dock = DockStyle.Fill;
            this.tabControl1.TabPages[index].Controls.Add(view);
        }

        private void GetFrmCtrl(Control ctrl)
        {
            foreach (Control item in ctrl.Controls)
            {
                Type type = item.GetType();
                if (type.Name != "Form" & item.Controls.Count > 0)
                    GetFrmCtrl(item);
                else if (type.Name == "Form")
                {
                    var sada = new BD_TextBox();
                    item.Controls.Add(sada);
                }
            }
        }

        private void removeSurface(Int32 index)
        {
            surface.RemoveAt(index);
            menuCommandService.RemoveAt(index);
        }

        /// <summary>
        ///  绑定选中属性
        /// </summary>
        /// <param name="index"></param>
        private void getSelectAttr(Int32 index)
        {
            this.propertyGrid1.SelectedObject = surface[index].ComponentContainer.Components[0];
            Object cp = pf.Filter(surface[index].ComponentContainer.Components[0]);
            propertyGrid1.SelectedObject = cp;
            selectionService = surface[index].GetService(typeof(ISelectionService)) as ISelectionService;
            selectionService.SelectionChanged += new EventHandler(selectionService_SelectionChanged);
        }

        private void change()
        {
            foreach (Control item in this.tabControl1.TabPages)
            {
                changeFormSize(item);
                item.Focus();
            }
        }

        private void changeFormSize(Control control)
        {
            foreach (Control ctrl in control.Controls)
            {
                var type = ctrl.GetType();
                if (type.Name == "Form")
                {
                    ctrl.Size = new Size(595, 790);
                    ((Form)ctrl).FormBorderStyle = FormBorderStyle;
                    break;
                }
                if (ctrl.Controls.Count > 0)
                    changeFormSize(ctrl);
            }
        }

        PropertyFilter pf = new PropertyFilter();//通过读取自定义样式文件来修改控件的属性
        //XmlDocument mXDoc = new XmlDocument();
        void selectionService_SelectionChanged(object sender, EventArgs e)
        {
            object[] selection;
            if (selectionService.SelectionCount == 0)
                propertyGrid1.SelectedObject = null;
            else
            {
                selection = new object[selectionService.SelectionCount];
                selectionService.GetSelectedComponents().CopyTo(selection, 0);

                //  this.SetControlText(selection);
                object cp = pf.Filter(selection[0]);
                propertyGrid1.SelectedObject = cp;
            }
        }

        private void deleteToolStripMenuItem_Click(object sender, EventArgs e)
        {
            var index = this.tabControl1.SelectedIndex;
            menuCommandService[index].GlobalInvoke(StandardCommands.Delete);
        }

        private void toolStripButton_Save_Click(object sender, EventArgs e)
        {

            var formName = TxtFormName.Text.Trim();
            if (String.IsNullOrEmpty(formName))
            {
                MessageBox.Show("表单名称必须填写");
                return;
            }

            for (int index = 0; index < tabControl1.TabPages.Count; index++)
            {
                if (!IsOkToSave(tabControl1.TabPages[index])) return;
            }

            XElement destiFile = (new SerializeDesigner().SerializeControlToXml(tabControl1, formName));
            SaveFileDialog saveFile = new SaveFileDialog();
            saveFile.InitialDirectory = "D:\\";
            saveFile.Filter = "压缩文件(*.rar)|*.rar|所有文件(*.*)|*.* ";
            if (saveFile.ShowDialog() == DialogResult.OK)
            {
                String destiStr = destiFile.ToString();
                String filePath = saveFile.FileName;
                String fileNameWithoutExten = Path.GetFileNameWithoutExtension(filePath);
                var matchStrs = Regex.Matches(destiStr, @"<Image>[a-zA-z]:(\\\w*){5,8}.\w*</Image>");
                List<String> listOriFilePath = new List<string>();

                // 遍历获得客户端本地图片地址
                foreach (var str in matchStrs)
                {
                    String oriFilePath = Regex.Match(str.ToString(), @"[a-zA-z]:(\\\w*){5,8}.\w*").ToString();
                    listOriFilePath.Add(oriFilePath);

                    // 修改图片路径
                    String picName = Path.GetFileName(oriFilePath);
                    destiStr = destiStr.Replace(oriFilePath, fileNameWithoutExten + "/" + picName);
                }

                // 保存修改并转换成XML格式
                destiFile = XElement.Parse(destiStr);

                // 创建模板文件
                String fileName = Path.Combine(Path.GetDirectoryName(filePath), fileNameWithoutExten);
                destiFile.Save(fileName + ".xml");

                // 创建文件
                ZipHelper zipHelper = new ZipHelper();
                zipHelper.CompressDirectory(listOriFilePath, fileName);
            }
            //serializedItems = new XElement("Form");
        }

        private void toolStripButton_Open_Click(object sender, EventArgs e)
        {
            if (fileDialog == null)
            {
                fileDialog = new OpenFileDialog();
                fileDialog.Filter = "压缩文件|*.rar|Xml文件|*.xml";
            }

            if (fileDialog.ShowDialog() == DialogResult.OK)
            {
                var fileName = fileDialog.FileName;
                var fileExternal = fileName.Substring(fileName.Length - 3).ToLower();
                if (fileExternal == "rar")
                {
                    var tempSavePath = Path.Combine(tempPath, Path.GetFileNameWithoutExtension(fileName));
                    if (!Directory.Exists(tempSavePath))
                        Directory.CreateDirectory(tempSavePath);
                    ZipHelper zipHelper = new ZipHelper();
                    zipHelper.DecompressFile(fileName, tempSavePath);
                    var dir = new DirectoryInfo(tempSavePath);
                    var files = dir.GetFiles();
                    foreach (var file in files)
                    {
                        var chiExternal = String.Empty;
                        chiExternal = file.Extension.ToLower();
                        if (chiExternal == ".xml")
                            fileName = file.FullName;
                    }
                }
                if (fileName.Substring(fileName.Length - 3).ToLower() == "xml")
                {
                    XElement xml = XElement.Load(fileName);
                    var tabs = xml.Elements().ToArray();
                    var tabCount = tabs.Count();

                    // 删除原有Tab
                    delAllTab();

                    var serialize = new SerializeDesigner();
                    for (int index = 0; index < tabCount; index++)
                    {
                        this.addTab();

                        IDesignerHost host = (IDesignerHost)surface[index].GetService(typeof(IDesignerHost));
                        serialize.DeserializeXmlToFrmCtrl(tabs[index], host);
                    }

                    this.getSelectAttr(0);
                    //this.tabControl1 = serialize.DeserializeXmlToFrmCtrl(xml, this.tabControl1);

                }
                else
                    MessageBox.Show("请选择正确的文件格式");
            }

        }

        private bool IsOkToSave(Control contr)
        {

            foreach (Control item in contr.Controls)
            {
                var thetype = item.GetType();
                //MessageBox.Show(item.Height.ToString());
                if (thetype.Name == "BD_Label" || thetype.Name == "BD_TextBox" ||
                    thetype.Name == "BD_RichTextBox" || thetype.Name == "BD_Button" ||
                    thetype.Name == "BD_RadioButton" || thetype.Name == "BD_CheckBox" ||
                    thetype.Name == "BD_ComboBox" || thetype.Name == "BD_DataGridView")
                {
                    if (string.IsNullOrEmpty(item.Name))
                    {
                        //(item.Parent as ContainerControl).ActiveControl = item;
                        this.ActiveControl = item;

                        MessageBox.Show("存在未命名控件，请确认");
                        ////item.Focus();
                        //item.Select();
                        return false;
                    }
                }
                if (item.Controls.Count > 0)
                    return IsOkToSave(item);
            }

            return true;
        }

        private void SetControlText(Object selectObj)
        {
            var control = selectObj as Control;
            Type type = control.GetType();
            switch (type.Name)
            {
                case "BD_DataGridView":
                    ((BD_DataGridView)selectObj).Name = "DataGridView" + BD_DataGridView.Count;
                    BD_DataGridView.Count++;
                    break;
                default:
                    break;
            }
        }

        private void FrmDesign_Shown(object sender, EventArgs e)
        {
        }

        private void toolStripButton1_Click(object sender, EventArgs e)
        {
            if (!IsOkToSave(splitContainer1.Panel1)) return;
        }

        private void toolStripButton_AddTab_Click(object sender, EventArgs e)
        {
            this.addTab();
        }

        private void toolStripButton_DelTab_Click(object sender, EventArgs e)
        {
            if (this.tabControl1.TabCount == 1)
                return;
            var index = this.tabControl1.SelectedIndex;
            this.delTab(index);
        }

        #endregion

        private void addTab()
        {
            var index = this.tabControl1.TabPages.Count;
            this.tabControl1.TabPages.Add("tabPage" + (index + 1));
            this.produSurface(index);
            change();
        }

        private void delTab(Int32 index)
        {
            if (tabControl1.TabPages.Count - 1 >= index)
            {
                this.tabControl1.TabPages.RemoveAt(index);
                this.removeSurface(index);
                change();
            }
        }

        private void delAllTab()
        {
            var tabCount = tabControl1.TabCount;
            for (int index = 0; index < tabCount; index++)
            {
                delTab(0);
            }
        }
    }
}
